// FaceFinder.h: interface for the CFaceFinder class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_FACEFINDER_H__6A58C7C0_D4F4_4904_A4C4_62C409BEC1BB__INCLUDED_)
#define AFX_FACEFINDER_H__6A58C7C0_D4F4_4904_A4C4_62C409BEC1BB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//#include "Preproc.h"
#include <vector>

using namespace std;
#define Define_Found_Face
#define STDIMAGESIZE      20
#define STARTSTEP         1.0

#define MAX_SCALE         200
#define MIN_STD_VARIANCE  324 //350 //324
#define MAX_STD_VARIANCE  3000
#define NUM_SMODEL        10


struct Found_Face
{
    DWORD  dwNumROI;  // number of faces found 
    RECT*  rcROI;

};

struct Model
{
	int m_nMaxLayNum;	// MaxLayerNum
	int maxT;		    // MaxFeatureNum

	int *cascade;
	double *finalthreshold;
	int (*finaltype)[6];
	double *finalh;
	int *finalsign;
	double *errorset;
	int *featureset;	
	int (*featurescale)[MAX_SCALE][4];
	double *apha;
	int abs;
};
struct SModel
{
	int FeatureNum;
	double * w;
	double * pFeature;
	double bias;
	int (*featurescale)[MAX_SCALE][4];
	int (*finaltype)[6];
};
struct PCAModel
{
	int FeatureNum;
	float apha[1500];
	int SelectFea[1500];
	float Threshold[1500];
	float finalThr;
	int   Sign[1500];
};
class CFaceFinder  
{
public:
	CFaceFinder();
	virtual ~CFaceFinder();
	BOOL m_bUse4Layer;
	double m_fThr[5]; // strore the threshold of different model

public:
	int CalSobel(int x, int y, int sizex, int sizey, int *Filter, int **imgsum);
	int Calc_Sum(int x1,int y1,int x2,int y2,int **imgsum);
	int GetThrMethod();
	void SetThrMethod(int nMethod);
	bool IsFace3(const int PosX, const int PosY, const int ScaleNo, float *pConfidence, int nLayer);
	inline int GetFeatureValue(int **itgimage, int type, int* pos, int PosX, int PosY, const int ScaleNo, int mir, int abs);
	bool IsFaceMir(const int PosX, const int PosY, const int ScaleNo);
	void Test1();
	void Test();
	BOOL IsFaceSubMdl(const int PosX, const int PosY, const int ScaleNo);
	int ChooseMdl(int **itgimage, const int PosX, const int PosY,const int WinSize);
	BOOL m_bAllLayer;
	bool IsFace2(const int PosX, const int PosY, const int ScaleNo, float &dbConfidence, int nLayer);
	void SetMirror(BOOL bMir);
	BOOL GetMirror();
	int GetMirrorFeatureX(int x, int mm, int width, int type);
	void SetPCA(BOOL bPCA);
	BOOL GetPCA( );
	Found_Face * DownDoFaceFinder(BYTE **ppImgOrg, const int nWidthOrg, const int nHeightOrg, BOOL bMirror = FALSE);
	void SetSModelLayer( int nLayer);
	int GetSModelLayer();
	void SetSModel(BOOL bsModel);
	BOOL GetSModel();
	bool IsFace1(const int PosX, const int PosY,const int ScaleNo, float& dbConfidence, int nLayer);
	void ReleaseSModel();
	BOOL LoadSModel(char * FileName);
	void ReSampleAt(int x, int y, int width, float& ratio , float& SumConf);
	double GetVariance(int x, int y, int winm, int winn);
	bool GetFaceConf(const int PosX, const int PosY,const int width, float& dbConfidence, float *pfConfidence);
	void SetConfidence(BOOL bConf);
	BOOL GetConfidence();
	double GetStartScale();
	void SeStartScal(double dbStartscale);
	float GetThrRatio();
	BOOL SetThreshold(float fRatio);
	BOOL LoadModelFromFile(CString szModelFileName[]);
	BOOL LoadOneModelFromFile(Model** m_pModel, CString szModelFileName);
	BOOL LoadOneModelFromResource(Model **m_ppModel);
	BOOL LoadPCAModel(CString filename);
	BOOL StrongClassify(PCAModel & pcaModel, float* pVector);
	int SimpleClassify(float* pVector, int nFea, int nWeakId);

	Found_Face *DoFaceFinder(BYTE **ppImage, const int nWidth, const int nHeight, BOOL bMirror = FALSE);

	void SetColorModel(BOOL bColor);
	void SetMinSize(int  nStdImageSize);
	void SetMaxScale(int nMaxScaleNum);
	void SetStep(int nStep);
	void SetMerge(BOOL bMerge);
	void SetMaxLayerNum(int nLayerNum);
	void SaveBmpImg(CString szFileName, BYTE* pImg, int nWidth, int nHeight);

	
	int     GetMinSize();
	int     GetMaxScale();
	int     GetStep();
	BOOL    GetMerge();
	BOOL    GetColor();
	int     GetMaxLayerNum();
	CString GetModelName();
	int m_nAbsFea; //0--not use abs feature; 1---all use abs feature; 2--all but first layer use abs feature 
	
private:
	inline BOOL   JudgeImage(int StartX, int StartY, int winsizeX, int winsizeY);
	inline void   GetFiFaiImg(BYTE **ppImg, const int nWidth, const int nHeight);
	inline void   GetGrayImg(BYTE **ppImg, const int nWidth, const int nHeight);
	inline int    GetFeatureValue(int **itgimage, int type, int mm, int nn, int x, int y);
	inline double GetVariance(int scalenum, int x, int y, int winm, int winn);
	inline void   GetItgImage(BYTE** pImage, int ImageWidth, int ImageHeight);
	inline double PrepareModel(const int StdImageSize);
	inline bool   IsFace_Cascade(const int PosX, const int PosY,const int ScaleNo, float& dbConfidence, float *pfConfidence);
	inline bool   IsFace(const int PosX, const int PosY,const int ScaleNo, float& dbConfidence, float *pfConfidence);

	inline int    GetFeatureValue(int **itgimage, int type, int* pos, int PosX, int PosY, const int ScaleNo);

	void          SAFE_RELEASE_MODEL(Model* pModel);
	
	BOOL  merge();

	//added by Qingdong Fu, Jan 3, 2002
	BOOL  merge1();

private:
	int m_nSModelLayer;
	BOOL m_bSModel;
	CString m_CurModelPath;
	int    m_nWidth;
	int    m_nHeight;
	BYTE** m_ppGrayImg;
	int** m_ppFiImg;
	int** m_ppFaiImg;

	int **m_ItgImageX;
	int **m_ItgImageXX;

	int    m_nWindowSize[MAX_SCALE];
	int    m_nWindowArea[MAX_SCALE];
	double m_dbScaleArea[MAX_SCALE];
	
	float  m_fConfThr[30000];
	double TrshHold[10000];
	float  m_fRatio;
	// four parameter used in algorithm :)
	BOOL   m_bColor;
	BOOL   m_bConfidence;
	int    m_nStdImageSize;
	int    m_nMaxScaleNum;
	int    m_nStep;
	double m_dbStartscale;
	BOOL   m_bMerge;
	BOOL   m_bPCA;
	int	   m_OriStdImageSize;
	BOOL   m_bMirror; //testing by the mirror images

	//added by Qingdong Fu
	BOOL   m_bMirrorDlg;

	double m_ScaleSize;

	int    m_nMaxLayerNum;
	int    m_nMaxFeatureNum;
	int    m_nFeatureNum;
	Model* m_pModel;
	Model* m_pArrModel[10];
	int m_nModel;
//  SModel m_SModel;
	SModel m_SModelArr[NUM_SMODEL];
	PCAModel m_PCAModel;
	PCAModel m_PCAModelArr[NUM_SMODEL];
	int    m_nSModelNum;
	int    m_nPCAModel;
	int m_nMethodThr;
	class CPosition
	{
	public:
		CPosition(int xx, int yy, int num, double dbConf): 
		  x(xx), y(yy), DetectionSum(num), Confidence(dbConf), FlagIntraScale(0), FlagInterScale(0) {};
		~CPosition() {};

		int x;
		int y;
		int DetectionSum;
		float Confidence;
		float sumConfidence;
		float MultiConf[20];
		float ratio;
		float avrConf;
		int FlagIntraScale;
		int FlagInterScale;
		int width;
		int height;
	};

	std::vector<CPosition> m_DetectionRect[MAX_SCALE];
	std::vector<CPosition> m_MergeRect[MAX_SCALE];

private:
	void ReSample();
	float m_rgbRToY[256];    // 299
    float m_rgbGToY[256];    // 587
    float m_rgbBToY[256];    // 114

	float m_rgbRToU[256];    
	float m_rgbGToU[256];
	float m_rgbBToU[256];

	float m_rgbRToV[256];    
	float m_rgbGToV[256];
	float m_rgbBToV[256];

	float m_rgbRToFI[256];    
	float m_rgbGToFI[256];
	float m_rgbBToFI[256];

	int   m_XXTable[256];    // XX
};

#endif // !defined(AFX_FACEFINDER_H__6A58C7C0_D4F4_4904_A4C4_62C409BEC1BB__INCLUDED_)
